package com.kongjs.application.util;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 快递订单流水号生成器
 * 格式：业务前缀 + 年月日 + 时分秒 + 站点码 + 序列号
 * 示例：EXP202306151430220010001
 */
public class ExpressNumberGenerator {
    // 业务前缀
    private final String businessPrefix;
    // 站点编码
    private final String stationCode;
    // 时间格式化
    private final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
    // 序列号
    private final AtomicInteger sequence = new AtomicInteger(0);
    // 最大序列号
    private final int maxSequence;
    // 上次生成时间
    private String lastDateTime = "";
    // 锁，保证线程安全
    private final Lock lock = new ReentrantLock();

    /**
     * 构造函数
     *
     * @param businessPrefix 业务前缀，如"EXP"
     * @param stationCode    站点编码，如"001"
     * @param sequenceLength 序列号长度
     */
    public ExpressNumberGenerator(String businessPrefix, String stationCode, int sequenceLength) {
        this.businessPrefix = businessPrefix;
        this.stationCode = stationCode;
        this.maxSequence = (int) Math.pow(10, sequenceLength) - 1;
    }

    /**
     * 生成下一个订单号
     */
    public String nextNumber() {
        lock.lock();
        try {
            String currentDateTime = formatCurrentDateTime();

            // 如果日期时间变化，重置序列号
            if (!currentDateTime.equals(lastDateTime)) {
                lastDateTime = currentDateTime;
                sequence.set(0);
            }

            // 获取序列号并格式化
            int currentSeq = sequence.getAndIncrement();

            // 如果序列号达到最大值，循环使用
            if (currentSeq > maxSequence) {
                sequence.set(0);
                currentSeq = 0;
            }

            String formattedSeq = String.format("%0" + String.valueOf(maxSequence).length() + "d", currentSeq);

            // 组装订单号
            return businessPrefix + currentDateTime + stationCode + formattedSeq;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 格式化当前日期时间
     */
    private String formatCurrentDateTime() {
        return LocalDateTime.now().format(dateFormatter);
    }

    // 示例使用
    public static void main(String[] args) {
        // 创建一个前缀为"EXP"，站点编码为"001"，序列号长度为5位的生成器
        ExpressNumberGenerator generator = new ExpressNumberGenerator("EXP", "001", 6);

        // 生成10个测试订单号
        for (int i = 0; i < 10; i++) {
            System.out.println(generator.nextNumber());
            // 模拟并发调用
            new Thread(() -> System.out.println(generator.nextNumber())).start();
        }
    }
}
